package com.yjb.tenet.boot.system.application.manager;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.http.HtmlUtil;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.yjb.tenet.boot.common.constants.GlobalConstants;
import com.yjb.tenet.boot.common.exception.CustomException;
import com.yjb.tenet.boot.common.exception.enums.ErrorCodeEnum;
import com.yjb.tenet.boot.framework.satoken.core.LoginUser;
import com.yjb.tenet.boot.framework.satoken.core.utils.SecurityFrameworkUtils;
import com.yjb.tenet.boot.system.application.service.SysNoticeReaderService;
import com.yjb.tenet.boot.system.application.service.SysNoticeService;
import com.yjb.tenet.boot.system.application.service.SysUserService;
import com.yjb.tenet.boot.system.domain.dto.SysNoticeDTO;
import com.yjb.tenet.boot.system.domain.entity.SysNotice;
import com.yjb.tenet.boot.system.domain.entity.SysNoticeReader;
import com.yjb.tenet.boot.system.domain.entity.SysUser;
import com.yjb.tenet.boot.system.domain.form.SysNoticeAddForm;
import com.yjb.tenet.boot.system.domain.form.SysNoticeEditForm;
import com.yjb.tenet.boot.system.infrastructure.enums.FlagEnums;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * @author zpc
 * @version 1.0
 * @description 系统通知manager
 * @create 2022/6/2 14:18
 */
@Component
public class SysNoticeMangager {

    @Resource
    private SysNoticeService sysNoticeService;

    @Resource
    private SysNoticeReaderService sysNoticeReaderService;

    @Resource
    private SysUserService sysUserService;

	/**
	 * 新增通知
	 *
	 * @param form
	 * @return
	 */
	@Transactional(rollbackFor = Exception.class)
	public boolean save(SysNoticeAddForm form, String ipAddr) {
		SysNotice sysNotice = new SysNotice();
		sysNotice.setIpAddr(ipAddr);
		BeanUtil.copyProperties(form, sysNotice);
		if (StrUtil.isBlank(sysNotice.getDigest())) {
			String sub = StrUtil.sub(
					HtmlUtil.cleanHtmlTag(sysNotice.getContent()), 0, 50)
					// 去除html标签里的空格换行符制表符
					.replace("&nbsp;", "")
					.replaceAll("\\s*|\t|\r|\n", "");
			sysNotice.setDigest(sub);
		}
		sysNoticeService.save(sysNotice);
		List<SysUser> list = sysUserService.lambdaQuery().eq(SysUser::getDeleted, GlobalConstants.NOT_DELETED).list();
		List readerList = new ArrayList();
		list.stream().forEach(sysUser -> {
			SysNoticeReader sysNoticeReader = new SysNoticeReader();
			sysNoticeReader.setNoticeId(sysNotice.getId());
			sysNoticeReader.setUserId(sysUser.getId());
			sysNoticeReader.setIsRead(FlagEnums.NO.getValue());
			readerList.add(sysNoticeReader);
		});
		return sysNoticeReaderService.saveBatch(readerList);
	}

	/**
	 * 编辑通知
	 *
	 * @param form
	 * @return
	 */
	public boolean edit(SysNoticeEditForm form, String ipAddr) {
		SysNotice sysNotice = sysNoticeService.lambdaQuery()
				.eq(SysNotice::getDeleted, GlobalConstants.NOT_DELETED)
				.eq(SysNotice::getId, form.getId())
				.one();
		if(FlagEnums.YES.getValue().equals(sysNotice.getPublished())){
			throw new CustomException(ErrorCodeEnum.BUSINESS_FAIL.getCode(), "通知已发布，不能编辑。");
		}
		sysNotice.setIpAddr(ipAddr);
		BeanUtil.copyProperties(form, sysNotice);
		if (StrUtil.isBlank(sysNotice.getDigest())) {
			String sub = StrUtil.sub(
					HtmlUtil.cleanHtmlTag(sysNotice.getContent()), 0, 50)
					// 去除html标签里的空格换行符制表符
					.replace("&nbsp;", "")
					.replaceAll("\\s*|\t|\r|\n", "");
			sysNotice.setDigest(sub);
		}
		return sysNoticeService.updateById(sysNotice);
	}

	/**
	 * 删除通知
	 *
	 * @param id
	 * @return
	 */
	public boolean delete(Long id) {
		SysNotice sysNotice = sysNoticeService.lambdaQuery()
				.eq(SysNotice::getDeleted, GlobalConstants.NOT_DELETED)
				.eq(SysNotice::getId, id)
				.one();
		sysNotice.setDeleted(sysNotice.getId());
		return sysNoticeService.updateById(sysNotice);
	}

	/**
	 * 我的通知中心
	 * @return
	 */
	public List<SysNoticeDTO> myNoticeList() {
		ArrayList<SysNoticeDTO> myNoticeList = new ArrayList<>();
		LoginUser loginUser = SecurityFrameworkUtils.getLoginUser();
		List<SysNoticeReader> sysNoticeReaderList = sysNoticeReaderService.lambdaQuery()
				.eq(SysNoticeReader::getUserId, loginUser.getId())
				.list();
		if(CollectionUtil.isEmpty(sysNoticeReaderList)){
			// 如果不存在发布给我的通知，直接返回
			return myNoticeList;
		}
		List<SysNotice> sysNoticeList = sysNoticeService.lambdaQuery().eq(SysNotice::getDeleted, GlobalConstants.NOT_DELETED)
				.eq(SysNotice::getPublished, FlagEnums.YES.getValue())
				.orderByDesc(SysNotice::getCreateTime)
				.list();
		sysNoticeList.stream().forEach(sysNotice -> {
			for (SysNoticeReader sysNoticeReader : sysNoticeReaderList){
				if(sysNotice.getId().equals(sysNoticeReader.getNoticeId())){
					SysNoticeDTO sysNoticeDTO = new SysNoticeDTO();
					sysNoticeDTO.setId(sysNotice.getId());
					sysNoticeDTO.setTitle(sysNotice.getTitle());
					sysNoticeDTO.setDigest(sysNotice.getDigest());
					sysNoticeDTO.setCreateTime(sysNotice.getCreateTime());
					sysNoticeDTO.setAuthor(sysNotice.getAuthor());
					sysNoticeDTO.setCover(sysNotice.getCover());
					sysNoticeDTO.setIsRead(sysNoticeReader.getIsRead());
					myNoticeList.add(sysNoticeDTO);
					break;
				}
			}
		});
		return myNoticeList;
	}
	
	/**
     * 已读
     * @param noticeId
     * @return
     */
    public boolean save(Long noticeId){
	    LoginUser loginUser = SecurityFrameworkUtils.getLoginUser();
	    LambdaUpdateWrapper<SysNoticeReader> set = new LambdaUpdateWrapper<SysNoticeReader>().ge(SysNoticeReader::getUserId, loginUser.getId())
			    .ge(SysNoticeReader::getNoticeId, noticeId)
			    .set(SysNoticeReader::getIsRead, FlagEnums.YES.getValue());
	    return sysNoticeReaderService.update(set);
    }

    /**
     * 根据id拿详情
     *
     * @param id
     * @return
     */
    public SysNotice getById(Long id) {
        return sysNoticeService.lambdaQuery()
                .eq(SysNotice::getDeleted, GlobalConstants.NOT_DELETED)
                .eq(SysNotice::getId, id)
                .one();
    }


    /**
     * 未读条数
     *
     * @return
     */
    public Long notReadCount() {
	    LoginUser loginUser = SecurityFrameworkUtils.getLoginUser();
	    Set<Long> noticeSet = sysNoticeService.lambdaQuery().eq(SysNotice::getDeleted, GlobalConstants.NOT_DELETED).list().stream().map(sysNotice -> {
		    return sysNotice.getId();
	    }).collect(Collectors.toSet());
	    if(CollectionUtil.isEmpty(noticeSet)) {
		    return 0L;
	    }
	    Long count = sysNoticeReaderService.lambdaQuery()
			    .in(SysNoticeReader::getNoticeId, noticeSet)
			    .eq(SysNoticeReader::getUserId, loginUser.getId())
			    .eq(SysNoticeReader::getIsRead, FlagEnums.NO.getValue())
			    .count();
	    return count;
    }
}
